#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <iostream>
#include <chrono>

#include <vector>
#include <random>

#include <thread> //使用标准库中的线程操作

#include <functional>

MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 配置连接： 点击按钮后创建一个线程产生随机数
    connect(ui->pushButton_generate, &QPushButton::clicked, this, [=]() {
        if (this->generateThread.joinable())
            generateThread.join(); // 等待之前的产生随机数线程完成
        int count = ui->spinBox_count->value();
        this->generateThread = std::thread(&MainWindow::generateRandomNumber, this, count);
    });

    // 配置连接： 接收产生的随机数，并显示
    connect(this, &MainWindow::generateAccomplish, this, [this]() {
        ui->listWidget->clear(); // 清除之前的数据
        // 显示在随机数列表中
        for (int i = 0; i < bubbleData.size() && i < 100; i++) // 只展示前100个，防止界面出问题
        {
            ui->listWidget->addItem(QString::number(bubbleData[i]));
        }
    });

    // 配置连接： 点击排序按钮后，创建线程进行排序
    connect(ui->pushButton_sort, &QPushButton::clicked, this, [=]() {
        if (this->bubbleThread.joinable())
            this->bubbleThread.join(); // 等待之前的冒泡排序完成
        if (this->quickThread.joinable())
            this->quickThread.join(); // 等待之前的快速排序线程完成

        ui->listWidget_bubble->clear(); // 清除之前展示的数据
        ui->listWidget_quick->clear();  // 清除之前展示的数据

        // 创建冒泡排序的线程，进行冒泡排序
        this->bubbleThread = std::thread(&MainWindow::bubbleSort, this, std::ref(this->bubbleData));
        // 创建快速排序的线程，进行快速排序
        this->quickThread = std::thread(&MainWindow::quickSort, this, std::ref(this->quickData));
    });

    // 配置连接： 排序完毕后显示结果
    // 冒泡排序
    connect(this, &MainWindow::bubbleSortAccomplish, this, [this]() {
        for (int i = 0; i < this->bubbleData.size() && i < 100; i++) // 只展示前100个，防止界面出问题
        {
            ui->listWidget_bubble->addItem(QString::number(bubbleData[i]));
        }
    });
    // 快速排序
    connect(this, &MainWindow::quickSortAccomplish, this, [this]() {
        for (int i = 0; i < this->quickData.size() && i < 100; i++) // 只展示前100个，防止界面出问题
        {
            ui->listWidget_quick->addItem(QString::number(quickData[i]));
        }
    });
}

MainWindow::~MainWindow()
{
    this->waitForAllThreads();
    delete ui;
}

void MainWindow::generateRandomNumber(int count)
{
    std::cout << "生成随机数开始" << std::endl;
    std::cout << "生成随机数 线程 ID" << std::this_thread::get_id() << std::endl;
    auto start = std::chrono::steady_clock::now();
    std::vector<int> randomVector;
    std::random_device seed;                               // 真随机数生成器，得到随机数种子
    std::mt19937 gen(seed());                              // 伪随机数生成引擎
    std::uniform_int_distribution distribution(0, 100000); // 分布器
    for (int i = 0; i < count; i++)
    {
        randomVector.push_back(distribution(gen));
    }

    // 记录数据，之后排序
    this->bubbleData = randomVector;
    this->quickData = randomVector;

    auto end = std::chrono::steady_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start); // 计算耗时
    std::cout << "生成随机数完成 用时 " << duration.count() << " 微秒" << std::endl;

    emit this->generateAccomplish();
}

void MainWindow::quickSort(std::vector<int>& dataVector)
{
    std::cout << "快速排序开始" << std::endl;
    std::cout << "快速排序 线程 ID" << std::this_thread::get_id() << std::endl;
    auto start = std::chrono::steady_clock::now();
    std::sort(dataVector.begin(), dataVector.end()); // 快速排序
    auto end = std::chrono::steady_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start); // 计算耗时
    std::cout << "快速排序完成 用时 " << duration.count() << " 微秒" << std::endl;
    emit this->quickSortAccomplish();
}

void MainWindow::bubbleSort(std::vector<int>& dataVector)
{
    std::cout << "冒泡排序开始" << std::endl;
    std::cout << "冒泡排序 线程 ID" << std::this_thread::get_id() << std::endl;

    auto start = std::chrono::steady_clock::now();

    // 冒泡排序
    int temporary;
    for (int i = 0; i < dataVector.size(); i++)
    {
        for (int j = 0; j < dataVector.size() - i - 1; j++)
        {
            if (dataVector[j] > dataVector[j + 1])
            {
                temporary = dataVector[j];
                dataVector[j] = dataVector[j + 1];
                dataVector[j + 1] = temporary;
            }
        }
    }

    auto end = std::chrono::steady_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start); // 计算耗时
    std::cout << "冒泡排序完成 用时 " << duration.count() << " 微秒" << std::endl;
    emit this->bubbleSortAccomplish();
}

void MainWindow::waitForAllThreads()
{
    if (this->generateThread.joinable())
    {
        this->generateThread.join();
    }
    if (this->quickThread.joinable())
    {
        this->quickThread.join();
    }
    if (this->bubbleThread.joinable())
    {
        this->bubbleThread.join();
    }
}
